using System;
using UnityEngine;
using UnityEngine.UI;

public class Entity_Health : MonoBehaviour, IDamagable
{
    public event Action OnTakeDamage;
    public event Action OnHealthChange;
    private Entity entity;
    protected Entity_Stat entityStat;
    private Health_Bar_Head barInHead;
    protected Slider headBar;
    private Entity_DropManager dropManager;

    [SerializeField] protected float currentHealth;

    public bool isDead { get; private set; } = false;


    [Header("-----Knock Back-----")]
    [SerializeField] private Vector2 knockBackMovement;
    [SerializeField] private float knockBackDuration;
    [Space]
    [SerializeField] private Vector2 heavyKnockBackMovement = new Vector2(7, 7);
    [SerializeField] private float heavyKnockBackDuration = .5f;
    [SerializeField] private float heavyDamageThresHold = .2f; //自身受到的伤害和当前血量的比值阈值

    [Header("Health Regenerate")]
    [SerializeField] private bool canRegenerateHealth = true;
    [SerializeField] private float regenInterval = 0.5f;
    public float lastTakeDamage { get; private set; }

    protected bool canTakeDamage = true;
    void Awake()
    {
        entity = GetComponent<Entity>();
        headBar = GetComponentInChildren<Slider>();
        barInHead = GetComponentInChildren<Health_Bar_Head>();
        dropManager = GetComponent<Entity_DropManager>();
        entityStat = GetComponent<Entity_Stat>();
        InvokeRepeating(nameof(RegenerateHealth), 0, regenInterval);
    }
    protected virtual void Start()
    {
        
    }
    protected virtual void OnEnable()
    {
        OnHealthChange += UpdateHealthBar;
        InitEntityHealth();
    }

    protected void OnDisable()
    {
        OnHealthChange -= UpdateHealthBar;
    }
    public void InitEntityHealth()
    {
        currentHealth = entityStat != null ? entityStat.GetMaxHealth() : 0;
        barInHead?.DisableHealthBar(true);
        
        //初始化更新血条
        UpdateHealthBar();
    }

    public virtual bool TakeDamage(float physicalDamage, float elementalDamage, ElementType elementType, Transform attacker, bool isCrit)
    {
        if (canTakeDamage == false || currentHealth <= 0 || AttackEvaded())
            return false;
        Entity_Stat attackerStats = attacker?.GetComponent<Entity_Stat>();
        Entity_Combat attackerCombat = attacker?.GetComponent<Entity_Combat>();
        //得到攻击者破甲系数
        float armorReduction = attackerStats != null ? attackerStats.GetArmorReduction() : 0;
        //传入攻击者破甲系数，得到计算后的防御系数
        float mitigation = entityStat != null ? entityStat.GetArmorMitigation(armorReduction) : 0;
        //计算防御后的受到的物理伤害
        float physicalDamageTaken = physicalDamage * (1 - mitigation);

        //得到元素防御系数
        float resistance = entityStat != null ? entityStat.GetElementalResistance(elementType) : 0;
        //计算元素防御后受到的元素伤害
        float elementalDamageTaken = elementalDamage * (1 - resistance);

        //记录上一次受到的伤害
        lastTakeDamage = physicalDamageTaken + elementalDamageTaken;

        //减少血量
        ReduceHealth(physicalDamageTaken + elementalDamageTaken);

        //执行受击事件
        OnTakeDamage?.Invoke();

        //击退效果处理
        KnockBackHandle(attacker, physicalDamageTaken);
        return true;

    }

    private void KnockBackHandle(Transform attacker, float physicalDamageTaken)
    {
        //获得计算后的击退位移
        Vector2 finalKnockBackMovement = CalculateKnockBack(physicalDamageTaken, attacker);
        //获得计算后的击退持续时间
        float finalDuration = CalculateDuration(physicalDamageTaken);
        //受击击退效果协程
        entity?.StartKnockBackCoroutine(finalKnockBackMovement, finalDuration);
    }
    public float GetCurrentHealth() => currentHealth;
    public float GetMaxHealth() => entityStat.GetMaxHealth();
    //得到当前生命值百分比
    public float GetCurrentHealthPercent() => currentHealth / entityStat.GetMaxHealth();
    //设置当前生命值（玩家释放碎片技能-位置交换回溯血量时调用）
    public void SetCurrentHealthPercent(float currentHealthPercent)
    {
        currentHealth = currentHealthPercent * entityStat.GetMaxHealth();
        UpdateHealthBar();
    }
    //生命再生
    public void RegenerateHealth()
    {
        if (!canRegenerateHealth || entityStat == null)
            return;
        float regenAmount = entityStat.resources.healthRegen.GetValue();
        IncreaseHealth(regenAmount);
    }
    //增加生命值
    public void IncreaseHealth(float regenAmount)
    {
        if (entityStat == null)
            return;
        float increasedHealth = currentHealth + regenAmount;
        float maxHealth = entityStat.resources.maxHealth.GetValue();
        currentHealth = Mathf.Min(increasedHealth, maxHealth);

        //广播健康值改变时的事件
        OnHealthChange?.Invoke();
    }

    //减少生命值
    public void ReduceHealth(float damage)
    {
        if (currentHealth <= 0)
            return;

        currentHealth -= damage;

        if (currentHealth <= 0)
        {
            Dead();
            currentHealth = Mathf.Max(0, currentHealth);
        }

        //广播健康值改变时的事件
        OnHealthChange?.Invoke();

    }

    public virtual void Dead()
    {
        isDead = true;
        entity.EntityDead();

        dropManager?.DropItem();

        barInHead?.DisableHealthBar(false);
    }

    [ContextMenu("Update HealthBar")]
    //更新血条
    private void UpdateHealthBar()
    {
        if (headBar == null || entityStat == null || headBar?.transform.parent.gameObject.activeSelf == false)
            return;
        float maxHealth = entityStat.GetMaxHealth();
        headBar.value = currentHealth / maxHealth;
    }


    //计算击退方向
    private Vector2 CalculateKnockBack(float damage, Transform attacker)
    {
        int knockBackDirection = transform.position.x > attacker.position.x ? 1 : -1;
        Vector2 _knockBack = IsHeavyDamage(damage) ? heavyKnockBackMovement : knockBackMovement;
        _knockBack.x *= knockBackDirection;
        return _knockBack;
    }

    //受击幸运
    private bool AttackEvaded()
    {
        if (entityStat == null)
            return false;
        return UnityEngine.Random.Range(0, 100) < entityStat.GetEvasion();
    }

    //判断是否是重击伤害
    private bool IsHeavyDamage(float damage)
    {
        if (entityStat == null)
            return false;
        float maxHealth = entityStat.GetMaxHealth();
        return damage / maxHealth > heavyDamageThresHold;
    }

    //计算击退距离
    private float CalculateDuration(float damage) => IsHeavyDamage(damage) ? heavyKnockBackDuration : knockBackDuration;
    public void SetCanTakeDamage(bool toggle) => canTakeDamage = toggle;
    protected void TriggerOnHealthChange() => OnHealthChange?.Invoke();
}
